package com.sec.bnjey.svc;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.widget.Toast;

import com.sec.bnjey.activity.MainActivity;
import com.sec.bnjey.bluetooth.BtService;
import com.sec.bnjey.bluetooth.BtUtil;
import com.sec.bnjey.global.Const;
import com.sec.bnjey.global.GlobalApplication;
import com.sec.bnjey.global.RbPreference;
import com.sec.bnjey.network.HttpPost;
import com.sec.bnjey.network.NetworkEventListener;
import com.sec.bnjey.network.SimpleCrypto;
import com.sec.bnjey.utils.RbLog;
import com.sec.bnjey.vo.DriveDetailEntity;

public class DaemonService extends Service implements NetworkEventListener {

	private static final String TAG = "DaemonService";

	private RbPreference mRbPreference;
	OBDDbHelper mOBDDbHelper;
	// OBDIndexDbHelper mOBDIndexDbHelper;
	private String booleanResult;
	private BroadcastReceiver mPowerKeyReceiver = null;
	int index_int = 0;
	SQLiteDatabase db;
	ContentValues row;
	Cursor cursor;
	int mileage = 0;
	int handler_start = 0;
	byte[] mObdRawData = new byte[66];
	byte[] b = new byte[16];

	byte[] d = new byte[64];
	byte[] xx = new byte[64];
	byte[] raw = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
			0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
	public static final String KEY_MILEAGE = "key_mileage";

	OBDUpdateHandler mOBDUpdateHandler;
	private int mOBDConnectionTryCnt;
	private boolean mBleutoothWasOn;

	int mReqLocalIndex;

	String result = null;
	String mHistory = "0";

	boolean mServiceFromMain = false;

	private boolean mOBDUpdateSuccess = false;

	public static boolean isDaemonRunning = false;

	String mSerialNumber, mPhoneNumber;
	DriveDetailEntity mDriveDetailInfo;
	long today;

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		RbLog.d(TAG, "onCreate()");

		mOBDUpdateSuccess = false;

		mRbPreference = new RbPreference(getApplicationContext());
		mSerialNumber = mRbPreference.getValue(RbPreference.PREF_SN, "");
		mPhoneNumber = mRbPreference.getValue(RbPreference.PREF_PHONE, "");

		IntentFilter deviceConnectedFilter;
		deviceConnectedFilter = new IntentFilter(
				android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED);
		this.registerReceiver(mPowerKeyReceiver, deviceConnectedFilter);

	}

	private void registBroadcastReceiver() {
		final IntentFilter theFilter = new IntentFilter();
		/** System Defined Broadcast */
		theFilter.addAction(Intent.ACTION_SCREEN_ON);
		theFilter.addAction(Intent.ACTION_SCREEN_OFF);

		mPowerKeyReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				String strAction = intent.getAction();
				BluetoothDevice device = intent
						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

				if (strAction.equals(Intent.ACTION_SCREEN_ON)) {
					RbLog.d(TAG, " --- ---  ACTION_SCREEN_ON  --- --- ");

					stopDeamonService();

				} else if (BluetoothDevice.ACTION_ACL_CONNECTED
						.equals(strAction)) {
					RbLog.d(TAG,
							" --- ---  CONNECT DEVICE NAME : "
									+ device.getName() + "  --- --- ");
				}

			}
		};

		getApplicationContext().registerReceiver(mPowerKeyReceiver, theFilter);
	}

	private void unregisterReceiver() {
		int apiLevel = Integer.parseInt(Build.VERSION.SDK);

		if (apiLevel >= 7) {
			try {
				getApplicationContext().unregisterReceiver(mPowerKeyReceiver);
			} catch (IllegalArgumentException e) {
				mPowerKeyReceiver = null;
			}
		} else {
			getApplicationContext().unregisterReceiver(mPowerKeyReceiver);
			mPowerKeyReceiver = null;
		}
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		RbLog.d(TAG, "=== onDestroy isrunning? " + isDaemonRunning);

		if (isDaemonRunning == true) {

			isDaemonRunning = false;

			if (mOBDUpdateHandler != null)
				mOBDUpdateHandler.removeCallbacksAndMessages(null);

			if (mServiceFromMain) {

			} else {
				RbLog.d(TAG, "bluetooth old was " + mBleutoothWasOn);

				if (mBleutoothWasOn == false) {

					// do not off bluetooth when bt is use with other profile.
					// if (getNowConnectedBTDevicesCnt() == 0) {
					// turn off bt
					RbLog.d(TAG, "Bt Disable");
					BtService.getBtService().disable();
					// }

					// BtService.getBtService().disable();
				}
				BtService.getBtService().stop();
				BtService.getBtService().closeSocket();

				GlobalApplication.stopBluetoothService();
			}

			unregisterReceiver();
		}
		super.onDestroy();
	}

	private void alarmCancel() {
		// cancel alarm
		RbLog.d(TAG, "=== setAlarm cancel ");
		// 알람 취소
		AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
		Intent intent = new Intent(this, VtalkBroadcastReceiver.class);
		PendingIntent sender = PendingIntent.getBroadcast(this, 1, intent, 0);
		am.cancel(sender);

	}

	public void alarmSetNext(int sec) {

		RbLog.d(TAG, "setAlarm after");

		// set new alarm
		RbLog.d(TAG, "=== setAlarm after " + sec + " sec");
		AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
		Intent intent = new Intent(getApplicationContext(),
				VtalkBroadcastReceiver.class);
		PendingIntent sender = PendingIntent.getBroadcast(
				getApplicationContext(), 1, intent, 0);
		am.set(AlarmManager.RTC_WAKEUP,
				System.currentTimeMillis() + sec * 1000, sender);

	}

	private NotificationManager nm;

	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);

		RbLog.d(TAG, "=== onStart");

		// cancel alarm
		alarmCancel();

		// get intent val
		if (intent != null) {
			Bundle extras = intent.getExtras();
			if (extras != null) {
				mServiceFromMain = extras.getBoolean("startFromMain");
				RbLog.d(TAG, "mServiceStartFromMain : " + mServiceFromMain);
			}
		}

		Date today = new Date();
		Calendar cal = Calendar.getInstance();
		cal.setTime(today);
		int NOW = cal.get(Calendar.HOUR_OF_DAY);

		isDaemonRunning = true;

		RbLog.d(TAG, "start from main ? " + mServiceFromMain);

		// check bluetooth status
		mBleutoothWasOn = BluetoothAdapter.getDefaultAdapter().isEnabled();// IKApplication.getBluetoothOldStatus();
		RbLog.d(TAG, "bluetooth old Status : " + mBleutoothWasOn);

		// song todo check network
		if (isValidNetworkStatus() == false) {
			stopDeamonService();
			return;
		}

		// form main
		if (mServiceFromMain) {

			// run without obd connection.
			RbPreference pref = new RbPreference(this);
			boolean withoutOBD = pref.getValue(
					RbPreference.PREF_RUN_WITHOUT_OBD, false);
			// stop daemon
			if (withoutOBD) {
				RbLog.e(TAG,
						"app is running without obd. so deamon will be finished.");
				stopDeamonService();
				pref.update(RbPreference.PREF_RUN_WITHOUT_OBD, false);
				return;
			}
		}
		// background service by alarm
		else {
			// 화면이 켜져 있으면 시작안함
			PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
			if (pm.isScreenOn()) {
				RbLog.d(TAG,
						"Screen is on. do nothing. so deamon will be finished.");
				stopDeamonService();
				return;
			}
		}

		BtService.getBtService().enable();

		registBroadcastReceiver();

		mOBDUpdateHandler = new OBDUpdateHandler();
		mOBDUpdateHandler.sendMessageDelayed(
				mOBDUpdateHandler.obtainMessage(DAEMON_STEP_INIT), 2000);

	}

	private boolean isValidNetworkStatus() {

		ConnectivityManager cManager;
		NetworkInfo mobile;
		NetworkInfo wifi;

		try {
			cManager = (ConnectivityManager) getApplicationContext()
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			mobile = cManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
			wifi = cManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

			if ((mobile != null && mobile.isConnected()) || wifi.isConnected()) {
				// 3G 또는 WiFi 에 연결되어 있을 경우
				RbLog.d(TAG, "Network Status is OK");
				return true;
			} else {
				RbLog.e(TAG, "Error Invalid Network Status");
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	private final int DAEMON_STEP_INIT = 0;
	private final int DAEMON_STEP_CONNECTION = 1;
	private final int DAEMON_STEP_CLOSE = 2;

	private final int DAEMON_STEP_FW_VERSIONCHECK = 20;

	private final int DAEMON_STEP_SYNC_INIT = 10;
	private final int DAEMON_STEP_SYNC_DRIVEDATA = 11;
	private final int DAEMON_STEP_SYNC_DRIVEDATA_HTTP = 12;
	private final int DAEMON_STEP_SYNC_DTCDATA = 13;

	class OBDUpdateHandler extends Handler {

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub

			super.handleMessage(msg);

			RbLog.d(TAG, "== OBDUpdateHandler what:" + msg.what
					+ " Bluetooth Status "
					+ BtService.getBtService().getBluetoothStatus());

			switch (msg.what) {

			// init
			case DAEMON_STEP_INIT: {
				RbLog.d(TAG, "DAEMON_STEP_INIT");
				mOBDConnectionTryCnt = 0;

				if (BtService.getBtService().isOBDDeviceConnected()) {
				} else {
					BtService.getBtService().start();
				}

				mOBDUpdateHandler
						.sendMessageDelayed(mOBDUpdateHandler
								.obtainMessage(DAEMON_STEP_CONNECTION), 1000);

				break;
			}

			// connection
			case DAEMON_STEP_CONNECTION: {

				if (BtService.getBtService().getBluetoothStatus() == BtService.STATE_CONNECTED) {

					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_INIT), 1000);

				} else if (BtService.getBtService().getBluetoothStatus() == BtService.STATE_CONNECTING
						|| BtService.getBtService().getBluetoothStatus() == BtService.STATE_NONE) {
					// pending
					mOBDConnectionTryCnt++;
					RbLog.d(TAG, "DAEMON_STEP_CONNECTION mOBDConnectionTryCnt "
							+ mOBDConnectionTryCnt);
					// timeout, close
					if (mOBDConnectionTryCnt > 10) {

						mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
								.obtainMessage(DAEMON_STEP_CLOSE), 0);
					}
					// monitoring
					else {

						mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
								.obtainMessage(DAEMON_STEP_CONNECTION), 1000);
					}
				}

				break;
			}

			// check FW version
			case DAEMON_STEP_FW_VERSIONCHECK: {
				RbLog.d(TAG, "DAEMON_STEP_FW_VERSIONCHECK");

				today = System.currentTimeMillis();
				int lastUpdateTime = mRbPreference.getValue(
						RbPreference.PREF_FIRMWARE_UPDATE_TIME, 0);

				int sevenDay = 60 * 60 * 24 * 7 * 1000;

				if (today - lastUpdateTime > sevenDay) {
					// check fw version
					obdReadFirmwareVersion();

				} else {
					// move to next step
					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_INIT), 1000);

				}

				break;
			}
			case DAEMON_STEP_SYNC_INIT: {
				RbLog.d(TAG, "DAEMON_STEP_SYNC_INIT");
				OBD_Init();

				if (Const.TESTMODE_STARTWITH0LASTINDEX) {
					mReqLocalIndex = 0;
					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_DRIVEDATA,
									mReqLocalIndex, 0), 0);

				} else {
					// get last index from server
					HttpPost.requestLastDriveIndex(mSerialNumber, mPhoneNumber,
							DaemonService.this);

				}

				break;
			}

			// get drive data and send
			case DAEMON_STEP_SYNC_DRIVEDATA: {
				RbLog.d(TAG, "DAEMON_STEP_SYNC_DRIVEDATA lastindex:"
						+ mReqLocalIndex);
				mOBDUpdateSuccess = true;
				if (obd_getOBDDriveData(mReqLocalIndex)) {

					// get drive info from raw data
					mDriveDetailInfo = obd_getDriveInfo(mReqLocalIndex);

					// send data to server.
					RbLog.d(TAG, "update obddata to server");
					HttpPost.sendDriveInfo(mSerialNumber, mPhoneNumber,
							mDriveDetailInfo, DaemonService.this);

				} else {
					// job finished
					// send msg to do next
					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_DTCDATA,
									mReqLocalIndex, 0), 0);
				}
				break;
			}

			// wait http response
			case DAEMON_STEP_SYNC_DRIVEDATA_HTTP: {
				RbLog.d(TAG, "DAEMON_STEP_SYNC_DRIVEDATA_HTTP");
				break;
			}

			// send dtc data to server
			case DAEMON_STEP_SYNC_DTCDATA: {
				RbLog.d(TAG, "DAEMON_STEP_SYNC_DTCDATA");
				obd_dtc();
				break;
			}

			// close
			case DAEMON_STEP_CLOSE: {
				RbLog.d(TAG, "DAEMON_STEP_CLOSE");
				mOBDUpdateHandler.removeCallbacksAndMessages(null);
				stopDeamonService();

				break;
			}

			default:
				break;
			}
		}
	}

	private void stopDeamonService() {
		RbLog.d(TAG, "stopDeamonService");

		if (isDaemonRunning == true) {
			// set next alarm
			RbLog.d(TAG, "mOBDUpdateSuccess " + mOBDUpdateSuccess);
			if (mOBDUpdateSuccess)
				alarmSetNext(Const.DELAY_TIME_TO_CHECK_SEC_SUCC);
			else
				alarmSetNext(Const.DELAY_TIME_TO_CHECK_SEC_FAILED);
		}

		stopService(new Intent(this, DaemonService.class));
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		RbLog.d(TAG, "onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	public void OBD_Init() {

		mOBDDbHelper = new OBDDbHelper(this);

		index_int = 0;

	}

	private void obd_storeFile(byte[] obdRequestIndex) {
		// i 저장
		File file1 = new File("/mnt/sdcard/vtalk/test/");
		File file2 = new File("/mnt/sdcard/vtalk/test/test.txt");

		try {

			if (!file2.exists()) {
				file1.mkdirs();
				file2.createNewFile();
			}

			@SuppressWarnings("resource")
			FileOutputStream fos = new FileOutputStream(
					"/mnt/sdcard/vtalk/test/test.txt");

			RbLog.d(TAG, "obd_savedata fwrite");

			fos.write(obdRequestIndex);
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private DriveDetailEntity obd_getDriveInfo(int reqLocalIndex) {

		System.arraycopy(mObdRawData, 2, xx, 0, 64);

		for (int j = 0; j < 4; j++) {
			try {
				byte[] c = new byte[32];
				System.arraycopy(xx, j * 16, c, 0, 16);
				c[16] = -107;
				c[17] = 79;
				c[18] = 100;
				c[19] = -14;
				c[20] = -28;
				c[21] = -24;
				c[22] = 110;
				c[23] = -98;
				c[24] = -18;
				c[25] = -126;
				c[26] = -46;
				c[27] = 2;
				c[28] = 22;
				c[29] = 104;
				c[30] = 72;
				c[31] = -103;

				b = SimpleCrypto.decrypt(raw, c);

				System.arraycopy(b, 0, d, j * 16, 16);
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		System.arraycopy(d, 0, mObdRawData, 2, 64);//

		DriveDetailEntity driveInfo = new DriveDetailEntity();

		driveInfo.setIndex(reqLocalIndex);
		handler_start = reqLocalIndex;

		byte[] start = new byte[4];
		System.arraycopy(mObdRawData, 19, start, 0, 4);
		driveInfo.setStarttime(BtUtil.Bytes2Int(start));

		byte[] end = new byte[4];
		System.arraycopy(mObdRawData, 23, end, 0, 4);
		driveInfo.setEndtime(BtUtil.Bytes2Int(end));

		byte[] mileage = new byte[4];
		System.arraycopy(mObdRawData, 27, mileage, 0, 4);
		driveInfo.setMileage(BtUtil.Bytes2Int(mileage));

		byte[] max_speed = new byte[1];
		System.arraycopy(mObdRawData, 31, max_speed, 0, 1);
		driveInfo.setMaxVss(BtUtil.Bytes2Int(max_speed));

		// support battery?
		byte[] sup_battery = new byte[1];
		System.arraycopy(mObdRawData, 38, sup_battery, 0, 1);

		driveInfo.supBat = BtUtil.Bytes2Int(sup_battery[0]);
		if (sup_battery[0] != 0x00) {
			byte[] max_battery = new byte[2];
			System.arraycopy(mObdRawData, 39, max_battery, 0, 2);
			driveInfo.setMaxBat(BtUtil.Bytes2Int(max_battery));

			byte[] min_battery = new byte[2];
			System.arraycopy(mObdRawData, 41, min_battery, 0, 2);
			driveInfo.setMinBat(BtUtil.Bytes2Int(min_battery));

			byte[] avg_battery = new byte[2];
			System.arraycopy(mObdRawData, 43, avg_battery, 0, 2);
			driveInfo.setAvgBat(BtUtil.Bytes2Int(avg_battery));

		} else {
			driveInfo.supBat = 0;
			int NULL = -99;
			driveInfo.setMaxBat(NULL);
			driveInfo.setMinBat(NULL);
			driveInfo.setAvgBat(NULL);
		}

		// support temperature
		byte[] sup_temp = new byte[1];
		System.arraycopy(mObdRawData, 45, sup_temp, 0, 1);

		if (sup_temp[0] != 0x00) {
			driveInfo.supCool = 1;
			byte[] temp = new byte[3];
			System.arraycopy(mObdRawData, 46, temp, 0, 3);
			driveInfo.setMaxCool((BtUtil.Bytes2Int(temp[0])));
			// min temp 1
			driveInfo.setAvgCool((BtUtil.Bytes2Int(temp[2])));
		} else {
			driveInfo.supCool = 0;
			int NULL = -99;
			driveInfo.setMaxCool(NULL);
		}

		// support engine oil temp
		byte[] sup_oil = new byte[1];
		System.arraycopy(mObdRawData, 49, sup_oil, 0, 1);

		if (sup_oil[0] != 0x00) {
			driveInfo.supEngine = 1;
			byte[] oil = new byte[3];
			System.arraycopy(mObdRawData, 50, oil, 0, 3); // 52,53,54
			driveInfo.setMaxEngine((BtUtil.Bytes2Int(oil[0])));
			driveInfo.setAvgEngine((BtUtil.Bytes2Int(oil[2])));
		} else {
			driveInfo.supEngine = 0;
			int NULL = -99;
			driveInfo.setMaxEngine(NULL);
			driveInfo.setAvgEngine(NULL);
		}

		// support fuel efficiency
		byte[] sup_fuel = new byte[1];
		System.arraycopy(mObdRawData, 53, sup_fuel, 0, 1);

		if (sup_fuel[0] != 0x00) {
			driveInfo.supEff = 1;
			byte[] fuel = new byte[2];
			System.arraycopy(mObdRawData, 54, fuel, 0, 2);

			driveInfo.setAvgEff((BtUtil.Bytes2Int(fuel)));
		} else {
			driveInfo.supEff = 0;
			int NULL = -99;
			driveInfo.setAvgEff(NULL);
		}

		// support consume oil
		byte[] sup_consume = new byte[1];
		System.arraycopy(mObdRawData, 56, sup_consume, 0, 1);

		if (sup_consume[0] != 0x00) {
			driveInfo.supfuelUse = 1;
			byte[] consume = new byte[2];
			System.arraycopy(mObdRawData, 57, consume, 0, 2);

			driveInfo.setFuelUse((BtUtil.Bytes2Int(consume)));
		} else {
			driveInfo.supfuelUse = 0;
			int NULL = -99;
			driveInfo.setFuelUse(NULL);
		}

		byte[] rapid = new byte[2];
		System.arraycopy(mObdRawData, 59, rapid, 0, 2);

		driveInfo.setAccelCnt((BtUtil.Bytes2Int(rapid[0])));
		driveInfo.setDecelCnt((BtUtil.Bytes2Int(rapid[1])));

		// �ְ�RPM
		byte[] maxrpm = new byte[2];
		System.arraycopy(mObdRawData, 61, maxrpm, 0, 2);

		driveInfo.setMaxRpm((BtUtil.Bytes2Int(maxrpm)));

		// ��ռӵ�
		byte[] avg_speed = new byte[1];
		System.arraycopy(mObdRawData, 63, avg_speed, 0, 1);

		driveInfo.setAvgVss((BtUtil.Bytes2Int(avg_speed)));

		// ��ȸ��ð�driveInfo
		byte[] idle = new byte[2];
		System.arraycopy(mObdRawData, 64, idle, 0, 2);

		driveInfo.setIdling((BtUtil.Bytes2Int(idle)));

		return driveInfo;

	}

	public boolean obd_getOBDDriveData(int requestOBDLocalIdx) {

		byte[] obdRequestIdx = { 0x00, 0x00 };

		result = null;
		RbLog.d(TAG, "obd_getOBDDriveData loop Index : " + requestOBDLocalIdx);

		// request obd term data
		obdRequestIdx = BtUtil.Int2Bytes(requestOBDLocalIdx, 2);
		mObdRawData = BtService.getBtService().OBD_TERM_DRIVE(obdRequestIdx);

		RbLog.d(TAG, "obd_getDriveData index:" + requestOBDLocalIdx + " data:"
				+ mObdRawData + " len " + mObdRawData.length);
		if (mObdRawData == null)
			return false;
		if (mObdRawData.length == 2) {
			return false;
		}

		if (mObdRawData[2] == -1) {
			return false;
		}

		return true;

	}

	public void obd_dtc() {
		RbLog.d(TAG, "obd_dtc");

		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		byte[] data = BtService.getBtService().OBD_TroubleCodeRequest();
		if (data != null) {
			ArrayList<String> codeList = null;

			/* for release */
			if (data != null) {
				codeList = BtUtil.getTroubleCodeList(data);
			}

			if (codeList != null && codeList.size() > 0) {
				String codes = "";
				for (int i = 0; i < codeList.size(); i++) {
					codes += codeList.get(i);
				}

				RbLog.d(TAG, "dtc code " + codes);

				// number
				HttpPost.sendDtc(mSerialNumber, mPhoneNumber, codeList.size(),
						codes, this);

				return;

			}
		}

		// dtc job finished.
		mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler.obtainMessage(
				DAEMON_STEP_CLOSE, mReqLocalIndex, 0), 100);

		return;
	}

	class OBDDbHelper extends SQLiteOpenHelper {
		public OBDDbHelper(Context context) {
			super(context, "Mileage49.db", null, 1);
		}

		public void onCreate(SQLiteDatabase db) {

			// String sqlQuery = "CREATE TABLE dic(" + "vid INTEGER,"
			// + "start INTEGER PRIMARY KEY," + "end INTEGER,"
			String sqlQuery = "CREATE TABLE dic(" + "vid INTEGER  PRIMARY KEY,"
					+ "start INTEGER," + "end INTEGER," + "mileage INTEGER,"
					+ "max_speed INTEGER," + "sup_battery INTEGER,"
					+ "max_battery INTEGER," + "min_battery INTEGER,"
					+ "avg_battery INTEGER," + "sup_temp INTEGER,"
					+ "max_temp INTEGER," + "avg_temp INTEGER,"
					+ "sup_oil INTEGER," + "max_oil INTEGER,"
					+ "avg_oil INTEGER," + "sup_fuel INTEGER,"
					+ "fuel INTEGER," + "sup_consume INTEGER,"
					+ "consume INTEGER," + "accelCnt INTEGER,"
					+ "decelCnt INTEGER," + "maxrpm INTEGER,"
					+ "avg_speed INTEGER," + "idle INTEGER," + "title BLOB(66)"
					+ ")";
			RbLog.d(TAG, sqlQuery);
			db.execSQL(sqlQuery);

		}

		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			db.execSQL("DROP TABLE IF EXISTS dic");
			onCreate(db);
		}
	}

	class OBDIndexDbHelper extends SQLiteOpenHelper {
		public OBDIndexDbHelper(Context context) {
			super(context, "Mileage50.db", null, 1);
		}

		public void onCreate(SQLiteDatabase db) {
			db.execSQL("CREATE TABLE dic (title TEXT)");

		}

		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			db.execSQL("DROP TABLE IF EXISTS dic");
			onCreate(db);
		}
	}

	private void dbInsert(DriveDetailEntity entity) {
		RbLog.d(TAG, "dbInsert");

		db = mOBDDbHelper.getWritableDatabase();
		row = new ContentValues();

		row.put("title", mObdRawData);
		row.put("vid", entity.vid);
		row.put("start", entity.starttime);
		row.put("end", entity.endtime);
		row.put("mileage", entity.mileage);
		row.put("max_speed", entity.maxVss);
		row.put("sup_battery", entity.supBat);
		row.put("max_battery", entity.maxBat);
		row.put("min_battery", entity.minBat);
		row.put("avg_battery", entity.avgBat);
		row.put("sup_temp", entity.supCool);
		row.put("max_temp", entity.maxCool);
		row.put("avg_temp", entity.avgCool);
		row.put("sup_oil", entity.supEngine);
		row.put("max_oil", entity.maxEngine);
		row.put("avg_oil", entity.avgEngine);
		row.put("sup_fuel", entity.supEff);
		row.put("fuel", entity.avgEff);
		row.put("sup_consume", entity.supfuelUse);
		row.put("consume", entity.fuelUse);
		row.put("accelCnt", entity.accelCnt);
		row.put("decelCnt", entity.decelCnt);
		row.put("maxrpm", entity.maxRpm);
		row.put("avg_speed", entity.avgVss);
		row.put("idle", entity.idling);

		db.insert("dic", null, row);
		mOBDDbHelper.close();

	}

	@Override
	public void onNetworkEvent(int type, Object retObject) {
		RbLog.e(TAG, "onNetworkEvent " + type);

		String result = (String) retObject;

		switch (type) {
		case HttpPost.NETWORK_DRIVEINFO:
			if (!result.isEmpty()) {

				if (result.substring(11, 15).equals("true")) {
					RbLog.e(TAG, " ----  success  ---- ");

					// convert raw data.
					dbInsert(mDriveDetailInfo);

					// send msg to do next
					mReqLocalIndex++;
					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_DRIVEDATA,
									mReqLocalIndex, 0), 0);

					mOBDUpdateSuccess = true;

					RbLog.e(TAG, "mReqLocalIndex " + mReqLocalIndex);

				} else {
					RbLog.e(TAG, " xxxxx  falied  xxxx ");
					mOBDUpdateSuccess = false;

					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_DTCDATA,
									mReqLocalIndex, 0), 0);
				}

			}
			break;
		case HttpPost.NETWORK_DTC:

			// finished to update dtc data
			mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
					.obtainMessage(DAEMON_STEP_CLOSE, mReqLocalIndex, 0), 0);
			break;

		case HttpPost.NETWORK_LASTDRIVEINDEX:

			if (!result.isEmpty()) {

				parseLastOBDData(result);

				if (booleanResult.equals("true")) {
					RbLog.d(TAG, " ----  NETWORK_LASTDRIVEINDEX success  ---- ");

					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_DRIVEDATA,
									mReqLocalIndex, 0), 0);

				} else {
					RbLog.e(TAG, " xxxxx  NETWORK_LASTDRIVEINDEX falied  xxxx ");
					mOBDUpdateSuccess = false;

					mOBDUpdateHandler.sendMessageDelayed(mOBDUpdateHandler
							.obtainMessage(DAEMON_STEP_SYNC_DTCDATA,
									mReqLocalIndex, 0), 0);
				}

			}
			break;

		default:
			break;
		}

	}

	private void parseLastOBDData(String lastIndexPath) {

		if (lastIndexPath == null || lastIndexPath.equals(""))
			return;

		try {
			JSONObject jsonObj = new JSONObject(lastIndexPath);
			booleanResult = jsonObj.getString("result");
			mReqLocalIndex = Integer.valueOf(jsonObj.getString("index"));
			RbLog.e(TAG,
					" ---- parse success result : "
							+ jsonObj.getString("result"));
			RbLog.e(TAG,
					" ---- parse success index : " + jsonObj.getString("index"));

			if (mReqLocalIndex > 0)
				mReqLocalIndex++;

			if (mReqLocalIndex > 27399)
				mReqLocalIndex = 0;

		} catch (JSONException e) {
			e.printStackTrace();
		}

	}

	private void callNotification() {
		// noti
		NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		PendingIntent intent = PendingIntent.getActivity(DaemonService.this, 0,
				new Intent(DaemonService.this, MainActivity.class), 0);

		String ticker = "ticker";
		String title = "title";
		String text = "text";

		// Create Notification Object
		Notification notification = new Notification(
				android.R.drawable.ic_input_add, ticker,
				System.currentTimeMillis());
		notification.flags = Notification.FLAG_AUTO_CANCEL;
		notification
				.setLatestEventInfo(DaemonService.this, title, text, intent);

		nm.notify(1234, notification);
	}

	private void obdReadFirmwareVersion() {

		RbLog.d(TAG, "obdReadFirmware");
		byte[] data = BtService.getBtService().OBD_FirmwareVersionRequest();

		if (data != null) {
			ArrayList<String> list = BtUtil.getVersions(data);

			String obd = list.get(0).substring(0, 4);

			// String server = getLatestFirmwareInfo();
			String server = Const.OBD_SERVER_FIRMWARE_VERSION;
			RbLog.d(TAG, "obd:" + obd + " server:" + server);

			if (server.equals(obd) == false) {

				// noti
				callNotification();
				// save last update time
				mRbPreference.update(RbPreference.PREF_FIRMWARE_UPDATE_TIME,
						(int) today);

			}
		}
		// version not found
		else {
			Toast.makeText(this, "Skip version check", Toast.LENGTH_LONG)
					.show();
		}

	}
}
